package com.jvm.interpreter.instruction;

import com.jvm.Utils;
import com.jvm.classfile.model.Class;
import com.jvm.classfile.model.CpInfo;
import com.jvm.classfile.model.Field;
import com.jvm.interpreter.Frame;
import com.jvm.interpreter.Instruction;
import com.jvm.interpreter.MetaSpace;

/**
 * @program: diy_simple_jvm
 * @description: getstatic指令
 * @author: CaoYong
 * @create: 2021-07-09 10:43
 **/
public class GetstaticInst implements Instruction {

    final String clazz;
    final String name;
    final String descriptor;

    public GetstaticInst(String clazz, String name, String descriptor) {
        this.clazz = clazz;
        this.name = name;
        this.descriptor = descriptor;
    }

    @Override
    public void eval(Frame frame) {
        // hack for java/lang/System.out
        if (clazz.equals("java/lang/System") && name.equals("out")) {
            frame.pushRef(null);
            frame.pc += offset();
            return;
        }

        final Class cls = MetaSpace.getClassLoader().findClass(clazz);
        Field field = cls.getStaticField(name, descriptor);
        Utils.clinit(field.clazz);

        field.get(frame);

        frame.pc += offset();
    }

    @Override
    public int offset() {
        return 3;
    }

    static GetstaticInst parse(java.io.DataInputStream dis, CpInfo[] cp) throws java.io.IOException {
        final int gsfi = dis.readUnsignedShort();
        return new GetstaticInst(Utils.getClassNameFromFieldRef(cp, gsfi), Utils.getNameFromFieldRef(cp, gsfi),
                Utils.getDescriptorFromFieldRef(cp, gsfi));
    }
}
